package com.chenfan.magic.config;

import com.alibaba.fastjson.JSONObject;
import com.chenfan.common.config.Constant;
import com.chenfan.common.exception.BusinessException;
import com.chenfan.common.exception.SystemState;
import com.chenfan.common.vo.Response;
import com.chenfan.common.vo.UserVO;
import com.chenfan.magic.constant.MagicConstant;
import com.chenfan.magic.constant.TokenConstant;
import com.chenfan.magic.entity.DataGroupDto;
import com.chenfan.magic.feign.PrivilegeServer;
import com.chenfan.magic.service.ShopComService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author liuming
 * @date 2021-03-29 13:41
 */
@Component
public class RequestParameterFilter extends OncePerRequestFilter {

    @Autowired
    private PrivilegeServer privilegeServer;

    @Autowired
    private ShopComService shopComService;

    @Autowired
    @Qualifier("redisTokenTemplate")
    private RedisTemplate redisTokenTemplate;


    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        if (request.getRequestURI().contains(MagicConstant.ALL_SHOPLIST_PATH)) {
            filterChain.doFilter(request, response);
            return;
        }
        String token = request.getHeader(Constant.AUTHORIZATION_TOKEN);
        String appKey = request.getHeader(TokenConstant.APP_KEY);
        //权限菜单在登录后,在[用户权限服务]中会把菜单放入缓存中
        UserVO user = getUserVO(request);

        String value = JSONObject.toJSONString(redisTokenTemplate.opsForValue().get(MagicConstant.USER_DATA_GROUP + user.getUserId()));
        List<DataGroupDto> list = null;
        if (!StringUtils.isEmpty(value) && !MagicConstant.NULL_STR.equals(value) && !MagicConstant.EMPTY_ARRAY_STR.equals(value)) {
            list = JSONObject.parseArray(value, DataGroupDto.class);
        } else {
            Response<List<DataGroupDto>> listResponse = privilegeServer.listByAppId(token, appKey);
            if (listResponse.getCode() != SystemState.SUCCESS.code()) {
                request.setAttribute("message", "不要着急，请稍后再试");
                //将异常分发到Exception控制器
                request.getRequestDispatcher("/magicException").forward(request, response);
            }
            list = Optional.ofNullable(listResponse).map(x -> x.getObj()).orElse(null);
        }

        if (CollectionUtils.isEmpty(list)) {
            request.setAttribute("message", "您的数据权限没有配置,请联系技术创新中心解决");
            //将异常分发到Exception控制器
            request.getRequestDispatcher("/magicException").forward(request, response);
        }
        String shopIds = mixed(list);
        //如果用户数据权限中包含-1(全部淘宝店铺),则只传入-1
        if (!StringUtils.isEmpty(shopIds) && shopIds.contains(MagicConstant.ALL_SHODIDS)) {
            shopIds = MagicConstant.ALL_SHODIDS;
        }
        Map paramter = new HashMap(16);
        paramter.put("shopIds", shopIds);
        paramter.put("userShopIds", list.stream().map(x -> String.valueOf(x.getGroupId())).collect(Collectors.joining(MagicConstant.COMMA)));
        ParameterRequestWrapper wrapper = new ParameterRequestWrapper(request, paramter);
        filterChain.doFilter(wrapper, response);
        return;
    }

    /**
     * 如果用户店铺数据域没有，则返回用户权限店铺数据
     * 如果用户店铺数据域有，则返回用户权限店铺数据+用户店铺数据域取交集
     * 对用户拥有权限的店铺列表和勾选的店铺数据域取交集
     *
     * @param list
     * @return
     */
    private String mixed(List<DataGroupDto> list) {
        Set<Long> set = list.stream().map(x -> x.getGroupId()).collect(Collectors.toSet());
        List<Long> domains = shopComService.getShopIds();
        if (CollectionUtils.isEmpty(domains)) {
            return set.stream().map(x -> String.valueOf(x)).collect(Collectors.joining(MagicConstant.COMMA));
        }
        List<Long> result = set.stream().filter(item -> domains.contains(item)).collect(Collectors.toList());
        result.add(0L);
        return result.stream().map(x -> String.valueOf(x)).collect(Collectors.joining(","));
    }

    /**
     * 获取用户信息
     *
     * @param request
     * @return
     */
    @Deprecated
    private UserVO getUserVO(HttpServletRequest request) {
        String token = request.getHeader(Constant.AUTHORIZATION_TOKEN);
        if (org.apache.commons.lang3.StringUtils.isEmpty(token)) {
            throw new BusinessException(Constant.UNAUTHORIZED, "用户登录信息失效");
        }
        UserVO attribute = JSONObject.parseObject(JSONObject.toJSONString(redisTokenTemplate.opsForValue().get(Constant.AUTHORIZATION + ":" + token)), UserVO.class);
        UserVoConstextHolder.setUserVo(attribute);
        return UserVoConstextHolder.getUserVo();
    }
}
